package com.reone.hookapi;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.util.Log;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class HookApi implements IXposedHookLoadPackage {
    private static final String TAG = "HookApi";

    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
        log("handleLoadPackage in HookApi:" + HookApi.class.getName());
        if (lpparam == null) {
            return;
        }
        log("Load app packageName:" + lpparam.packageName);
        logMethod(android.content.ContextWrapper.class.getName(), lpparam.classLoader, "attachBaseContext", Context.class);
        logMethod(androidx.fragment.app.FragmentActivity.class.getName(), lpparam.classLoader, "onActivityResult", int.class, int.class, Intent.class);
        logMethod(android.telephony.TelephonyManager.class.getName(), lpparam.classLoader, "getDeviceId");
        logMethod(android.telephony.TelephonyManager.class.getName(), lpparam.classLoader, "getDeviceId", int.class);
        logMethod(android.telephony.TelephonyManager.class.getName(), lpparam.classLoader, "getSubscriberId", int.class);
        logMethod(android.net.wifi.WifiInfo.class.getName(), lpparam.classLoader, "getMacAddress");
        logMethod(java.net.NetworkInterface.class.getName(), lpparam.classLoader, "getHardwareAddress");
        logMethod(android.provider.Settings.Secure.class.getName(), lpparam.classLoader, "getString", ContentResolver.class, String.class);
        logMethod(LocationManager.class.getName(), lpparam.classLoader, "getLastKnownLocation", String.class);
    }

    private void log(String log) {
        XposedBridge.log(log);
        Log.d(TAG, log);
    }

    private void logMethod(String className, ClassLoader classLoader, final String methodName, Object... parameterTypesAndCallback) {
        int count = parameterTypesAndCallback.length + 1;
        Object[] ot = new Object[count];
        for (int i = 0; i < count; i++) {
            if (i == count - 1) {
                ot[i] = new XC_MethodHook() {
                    @Override
                    protected void beforeHookedMethod(MethodHookParam param) {
                        log("检测到调用了:" + methodName);
                    }

                    @Override
                    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                        log(getMethodStack());
                        super.afterHookedMethod(param);
                    }
                };
            } else {
                ot[i] = parameterTypesAndCallback[i];
            }
        }
        XposedHelpers.findAndHookMethod(className, classLoader, methodName, ot);
    }

    private String getMethodStack() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();

        StringBuilder stringBuilder = new StringBuilder();

        for (StackTraceElement temp : stackTraceElements) {
            stringBuilder.append(temp.toString() + "\n");
        }

        return stringBuilder.toString();
    }
}
